package com.twb.wechat.controller;

import com.alibaba.fastjson.JSON;
import com.twb.core.base.Result;
import com.twb.core.base.controller.BaseController;
import com.twb.core.security.annotation.Auth;
import com.twb.core.util.Results;
import com.twb.wechat.cp.config.WxCpConfiguration;
import com.twb.wechat.cp.utils.WxCpMessageSend;
import com.twb.wechat.entity.vo.NewsMessageVo;
import com.twb.wechat.entity.vo.TextMessageVo;
import com.twb.wechat.service.ITwbWxCpService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import java.util.ArrayList;
import java.util.List;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpDepartmentService;
import me.chanjar.weixin.cp.api.WxCpOAuth2Service;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.api.WxCpUserService;
import me.chanjar.weixin.cp.bean.WxCpDepart;
import me.chanjar.weixin.cp.bean.WxCpOauth2UserInfo;
import me.chanjar.weixin.cp.bean.WxCpUser;
import me.chanjar.weixin.cp.util.crypto.WxCpCryptUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author DSY
 * @Title WxCpController.java
 * @Description 微信企业号
 * @date 2021年8月15日 下午4:34:19
 */
@RestController
@RequestMapping("/wx/cp")
@Api(value = "WxMpController", tags = "微信企业号 服务接口")
public class WxCpController extends BaseController {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    ITwbWxCpService twbWxCpService;

    /**
     * 构建身份验证url
     *
     * @param agentId
     * @param state       状态
     * @param redirectUrl 重定向url
     * @param domain      域
     * @return {@link Result }<{@link String }>
     * @author DHL
     * @date 2023-01-30 10:10:05
     */
    @Auth(verifyToken = false, verifyURL = false)
    @GetMapping("/buildAuthUrl")
    public Result<String> buildAuthUrl(
        @RequestParam(name = "agentId", required = true) Integer agentId,
        @RequestParam(name = "state", required = false) String state,
        @RequestParam(name = "redirectUrl", required = true) String redirectUrl,
        @RequestParam(name = "domain", required = true) String domain
    ) {
        WxCpService wxCpService = twbWxCpService.getWxCpService(agentId, domain);

        if (wxCpService == null) {
            return Results.failure(String.format("未找到对应agentId=[%d]的配置，请核实！", agentId));
        }
        WxCpOAuth2Service oauth2Service = wxCpService.getOauth2Service();
        String url = oauth2Service.buildAuthorizationUrl("123");
        return Results.successWithData(url);
    }

    /**
     * @param agentId
     * @param code
     * @return
     * @Title getUserInfo
     * @Description 获取用户信息
     * @AuthorOriginally DSY
     * @date 2022年12月3日 下午5:11:10
     */
    @Auth(verifyToken = false, verifyURL = false)
    @GetMapping("/getUserInfo")
    public Result<WxCpUser> getUserInfo(
        @RequestParam(name = "agentId", required = true) Integer agentId,
        @RequestParam(name = "code", required = true) String code,
        @RequestParam(name = "domain", required = true) String domain
    ) {
        WxCpService wxCpService = twbWxCpService.getWxCpService(agentId, domain);

        if (wxCpService == null) {
            return Results.failure(String.format("未找到对应agentId=[%d]的配置，请核实！", agentId));
        }
        WxCpOAuth2Service oauth2Service = wxCpService.getOauth2Service();
        WxCpOauth2UserInfo userInfo = null;
        try {
            userInfo = oauth2Service.getUserInfo(agentId, code);
            logger.info("企业微信用户获取成功：" + JSON.toJSONString(userInfo));
        } catch (WxErrorException e) {
            logger.error(e.getMessage());
            return Results.failure("微信授权无效，请刷新重试!" + e.getMessage());
        }
        if (userInfo == null) {
            return Results.failure("企业微信用户获取失败！请刷新重试!");
        }
        try {
            WxCpUserService userService = wxCpService.getUserService();
            String userId = userInfo.getUserId();
            String openId = userInfo.getOpenId();
            //如果userId为空，openId不为空，则通过openid获取userId
            if (StringUtils.isBlank(userId) && StringUtils.isNotBlank(openId)) {
                userId = userService.openid2UserId(openId);
                logger.info("企业微信用户userId为空：openid=" + openId + " userid=" + userId);
            }
            WxCpUser wxCpUser = userService.getById(userId);
            return Results.successWithData(wxCpUser);
        } catch (WxErrorException e) {
            return Results.failure(e.getMessage());
        }
    }

    /**
     * @param agentId
     * @param userId
     * @return
     * @Title getUserInfoById
     * @Description 获取用户信息
     * @AuthorOriginally DSY
     * @date 2022年11月28日 上午11:30:28
     */
    @Auth(verifyToken = false, verifyURL = false)
    @GetMapping("/getUserInfoById")
    public Result<WxCpUser> getUserInfoById(
        @RequestParam(name = "agentId", required = true) Integer agentId,
        @RequestParam(name = "userId", required = true) String userId,
        @RequestParam(name = "domain", required = true) String domain
    ) {
        WxCpService wxCpService = twbWxCpService.getWxCpService(agentId, domain);
        if (wxCpService == null) {
            return Results.failure(String.format("未找到对应agentId=[%d]的配置，请核实！", agentId));
        }
        try {
            WxCpUserService userService = wxCpService.getUserService();
            WxCpUser wxCpUser = userService.getById(userId);
            return Results.successWithData(wxCpUser);
        } catch (WxErrorException e) {
            return Results.failure(e.getMessage());
        }
    }

    /**
     * @param agentId
     * @param userId
     * @return
     * @Title getUserDepartment
     * @Description 获取用户所属部门
     * @AuthorOriginally DSY
     * @date 2022年11月28日 上午11:27:43
     */
    @Auth(verifyToken = false, verifyURL = false)
    @GetMapping("/getUserDepartment")
    public Result<List<WxCpDepart>> getUserDepartment(
        @RequestParam(name = "agentId", required = true) Integer agentId,
        @RequestParam(name = "userId", required = true) String userId,
        @RequestParam(name = "domain", required = true) String domain
    ) {
        WxCpService wxCpService = twbWxCpService.getWxCpService(agentId, domain);
        if (wxCpService == null) {
            return Results.failure(String.format("未找到对应agentId=[%d]的配置，请核实！", agentId));
        }
        List<WxCpDepart> depts = new ArrayList<WxCpDepart>();
        try {
            WxCpUserService userService = wxCpService.getUserService();
            WxCpDepartmentService departmentService = wxCpService.getDepartmentService();
            WxCpUser wxCpUser = userService.getById(userId);
            Long[] departIds = wxCpUser.getDepartIds();
            for (Long id : departIds) {
                WxCpDepart wxCpDepart = departmentService.get(id);
                System.out.println(wxCpDepart.getName());
                depts.add(wxCpDepart);
            }
            return Results.successWithData(depts);
        } catch (WxErrorException e) {
            return Results.failure(e.getMessage());
        }
    }

    @GetMapping(produces = "text/plain;charset=utf-8")
    public String authGet(@PathVariable Integer agentId,
        @RequestParam(name = "msg_signature", required = false) String signature,
        @RequestParam(name = "timestamp", required = false) String timestamp,
        @RequestParam(name = "nonce", required = false) String nonce,
        @RequestParam(name = "echostr", required = false) String echostr,
        @RequestParam(name = "domain", required = true) String domain
    ) throws WxErrorException {
        this.logger.info("\n接收到来自微信服务器的认证消息：signature = [{}], timestamp = [{}], nonce = [{}], echostr = [{}]",
            signature, timestamp, nonce, echostr);

        if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) {
            throw new IllegalArgumentException("请求参数非法，请核实!");
        }

        WxCpService wxCpService = twbWxCpService.getWxCpService(agentId, domain);
        if (wxCpService == null) {
            throw new IllegalArgumentException(String.format("未找到对应agentId=[%d]的配置，请核实！", agentId));
        }

        if (wxCpService.checkSignature(signature, timestamp, nonce, echostr)) {
            return new WxCpCryptUtil(wxCpService.getWxCpConfigStorage()).decrypt(echostr);
        }

        return "非法请求";
    }

    /**
     * @param vo
     * @return
     * @Title sendNewsMessage
     * @Description 推送图文消息
     * @AuthorOriginally 杜顺亚
     * @date 2021年9月28日 上午11:47:24
     */
    @Auth(verifyToken = false, verifyURL = false)
    @PostMapping("/sendNewsMessage")
    @ApiOperation(value = "发送图文消息")
    public Result<String> sendNewsMessage(@RequestBody NewsMessageVo vo) {
        try {
            WxCpMessageSend.newsCard(vo.getAgentId(), vo.getToUser(), vo.getArticles());
            return Results.success("消息推送成功");
        } catch (WxErrorException e) {
            return Results.failure("消息推送失败");
        }
    }

    /**
     * @param vo
     * @return
     * @Title sendTextMessage
     * @Description 发送文本消息
     * @AuthorOriginally 杜顺亚
     * @date 2021年9月30日 下午12:04:16
     */
    @Auth(verifyToken = false, verifyURL = false)
    @PostMapping("/sendTextMessage")
    @ApiOperation(value = "发送文本消息")
    public Result<String> sendTextMessage(@RequestBody TextMessageVo vo) {
        try {
            WxCpMessageSend.textCard(vo.getAgentId(), vo.getToUser(), vo.getTitle(), vo.getDescription(), vo.getUrl());
            return Results.success("消息推送成功");
        } catch (WxErrorException e) {
            return Results.failure("消息推送失败");
        }
    }

    /**
     * @param agentId
     * @param departId
     * @return
     * @Title listDepartments
     * @Description 获取部门
     * @AuthorOriginally 杜顺亚
     * @date 2022年11月29日 上午10:13:16
     */
    @Auth(verifyToken = false, verifyURL = false)
    @GetMapping("/listDepartments")
    public Result<List<WxCpDepart>> listDepartments(@RequestParam(name = "agentId", required = true) Integer agentId, @RequestParam(name = "departId", required = false) Long departId) {
        final WxCpService wxCpService = WxCpConfiguration.getCpService(agentId);
        if (wxCpService == null) {
            return Results.failure(String.format("未找到对应agentId=[%d]的配置，请核实！", agentId));
        }
        List<WxCpDepart> depts = new ArrayList<WxCpDepart>();
        try {
            WxCpDepartmentService departmentService = wxCpService.getDepartmentService();
            depts = departmentService.list(departId);
            return Results.successWithData(depts);
        } catch (WxErrorException e) {
            return Results.failure(e.getMessage());
        }
    }
}
